package infraestructura;

import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import modelo.Comment;
import modelo.Pedido;
import modelo.Product;
import modelo.User;

public class PersistenceManager {

    private UserPersistence userPersistence;
    private ProductPersistence productPersistence;
    private CommentPersistence commentPersistence;
    private PedidoPersistence pedidoPersistence;
    private static PersistenceManager persistenceManager = null;
    
    private final ReentrantReadWriteLock productLock = new ReentrantReadWriteLock();
    private final ReadLock readLock = productLock.readLock();
    private final WriteLock writeLock = productLock.writeLock();

    private PersistenceManager(String initParam) {
        userPersistence = UserDAO.getDAO(initParam);
        productPersistence = ProductDAO.getDAO(initParam);
        commentPersistence = CommentDAO.getDAO(initParam);
        pedidoPersistence = PedidoDAO.getDAO(initParam);
    }
    //@Abraham Esto es precisamente uno de los problemas de concurrencia temor descrito en PED...
    //podría crearse mas de un persistenceManager
    public static PersistenceManager getPersistenceManager(String initParam) {
        
        if (persistenceManager == null) {
            persistenceManager = new PersistenceManager(initParam);
        }
        return persistenceManager;
    }

    public boolean userExists(String username, String password) {
        return userPersistence.userExists(username, password);
    }
    
    public boolean userExists(String username) {
        return userPersistence.userExists(username);
    }

    public User getUser(String username, String password) {
        return userPersistence.getUser(username, password);
    }
    
    public User getUser(int id) {
        return userPersistence.getUser(id);
    }
    
    public int createUser(User user) {
        return userPersistence.createUser(user);
    }

    public boolean existsProduct(String name) {
        //@Abraham debería coger lock de lectura
        return productPersistence.exists(name);
    }

    public boolean existsProdut(int id) {
        //@Abraham debería coger lock de lectura
        return productPersistence.exists(id);
    }

    public int getTheIdOfTheProduct(String name) {
        //@Abraham debería coger lock de lectura
        return productPersistence.getTheId(name);
    }

    public Product getProduct(int id) {
        readLock.lock();
        Product product = productPersistence.getProduct(id);
        readLock.unlock();
        return product;
    }

    public List<Product> getALLTheProducts() {
        //@Abraham debería coger lock de lectura, y lo mismo para cualquier otro uso
        return productPersistence.getALLTheProducts();
    }

    public void createProduct(Product product) {
        productPersistence.createProduct(product);
    }

    public void updateProduct(int id, Product product) {
        writeLock.lock();
            productPersistence.updateProduct(id, product);
        writeLock.unlock();
    }

    public void deleteProduct(int id) {
        writeLock.lock();
            productPersistence.deleteProduct(id);
        writeLock.unlock();
    }

    public void addComment(Comment comment) {
        //@Abraham Aqui también hay que coger lock 
        //Ya que internamente va a tocar los productos
        commentPersistence.addComment(comment);
    }

    public List<Comment> getCommentsForProduct(int productId) {
        //@Abraham Aqui también hay que coger lock 
        //Ya que internamente va a tocar los productos
        return commentPersistence.getCommentsForProduct(productId);
    }

    public int addPedido(Pedido pedido) {
        return pedidoPersistence.add(pedido);
    }

    public List<Pedido> getALLThePedidos() {
        return pedidoPersistence.getALLThePedidos();
    }

    public boolean existsThePedido(int pedidoId) {
        return pedidoPersistence.existsThePedido(pedidoId);
    }

    public Pedido getThePedido(int pedidoId) {
        return pedidoPersistence.getThePedido(pedidoId);
    }

    public void updateStock(int id, int cantidad) {
        writeLock.lock();
        productPersistence.updateStock(id, cantidad);
        writeLock.unlock();
    }

}
